import { material, project } from '@alilc/lowcode-engine';
import { filterPackages } from '@alilc/lowcode-plugin-inject'
import { Message, Dialog } from '@alifd/next';
import { IPublicTypeProjectSchema, IPublicEnumTransformStage, IPublicModelPluginContext } from '@alilc/lowcode-types';
import _isEmpty from 'lodash/isEmpty';
import _merge from 'lodash/merge';
import DefaultPageSchema from './defaultPageSchema.json';
import DefaultI18nSchema from './defaultI18nSchema.json';
import { isDef } from '@/shared/functions';
import { constants } from '@/appHelper';

export const generateProjectSchema = (pageSchema: any, i18nSchema: any): IPublicTypeProjectSchema => {
  return {
    componentsTree: [pageSchema],
    componentsMap: material.componentsMap as any,
    version: '1.0.0',
    i18n: i18nSchema,
  };
}

export const saveSchema = async (id: string, ctx: IPublicModelPluginContext) => {
  setProjectSchemaToLocalStorage(id, ctx);
  await setPackagesToLocalStorage(id, ctx);
  Message.success('成功保存到本地');
};

export const resetSchema = async (id: string, ctx: IPublicModelPluginContext) => {
  try {
    await new Promise<void>((resolve, reject) => {
      Dialog.confirm({
        content: '确定要重置吗？您所有的修改都将消失！',
        onOk: () => {
          resolve();
        },
        onCancel: () => {
          reject()
        },
      })
    })
  } catch(err) {
    return;
  }
  const defaultSchema = generateProjectSchema(DefaultPageSchema, DefaultI18nSchema);

  project.importSchema(defaultSchema as any);
  project.simulatorHost?.rerender();

  setProjectSchemaToLocalStorage(id, ctx);
  await setPackagesToLocalStorage(id, ctx);
  Message.success('成功重置页面');
}

export const removeSchema = async (id: string, ctx: IPublicModelPluginContext) => {
  const scenarioName = ctx.config.get('scenarioName');
  if (!scenarioName) {
    console.error('scenarioName is required!');
    return;
  }
  window.localStorage.removeItem(getLSName(scenarioName, id));
  window.localStorage.removeItem(getLSName(scenarioName, id, 'packages'));
}

const getLSName = (scenarioName: string, id?: string, ns: string = 'projectSchema') => (isDef(id) ? `${scenarioName}:${id}:${ns}` : `${scenarioName}:${ns}`);

const getResourceName = (scenarioName: string, ns: string = 'resourceList') => `${scenarioName}:${ns}`;

export const setResourceListToLocalStorage = async (scenarioName: string, list: any) => {
  if (!scenarioName) {
    console.error('scenarioName is required!');
    return;
  }

  window.localStorage.setItem(
    getResourceName(scenarioName),
    JSON.stringify(list)
  );
}

export const getResourceListFromLocalStorage = async (scenarioName: string) => {
  if (!scenarioName) {
    console.error('scenarioName is required!');
    return;
  }
  return JSON.parse(window.localStorage.getItem(getResourceName(scenarioName)) || '[]');
}

export const getProjectSchemaFromLocalStorage = (scenarioName: string, id?: string) => {
  if (!scenarioName) {
    console.error('scenarioName is required!');
    return;
  }
  const localValue = window.localStorage.getItem(getLSName(scenarioName, id));
  if (localValue) {
    return JSON.parse(localValue);
  }
  return undefined;
}

const setProjectSchemaToLocalStorage = (id: string, ctx: IPublicModelPluginContext) => {
  const scenarioName = ctx.config.get('scenarioName');
  if (!scenarioName) {
    console.error('scenarioName is required!');
    return;
  }
  window.localStorage.setItem(
    getLSName(scenarioName, id),
    JSON.stringify(ctx.project.exportSchema(IPublicEnumTransformStage.Save))
  );
}

const setPackagesToLocalStorage = async (id: string, ctx: IPublicModelPluginContext) => {
  const scenarioName = ctx.config.get('scenarioName');
  if (!scenarioName) {
    console.error('scenarioName is required!');
    return;
  }
  const packages = await filterPackages(ctx.material.getAssets().packages);
  window.localStorage.setItem(
    getLSName(scenarioName, id, 'packages'),
    JSON.stringify(packages),
  );
}

export const getPackagesFromLocalStorage = (scenarioName: string, id: string) => {
  if (!scenarioName) {
    console.error('scenarioName is required!');
    return;
  }
  return JSON.parse(window.localStorage.getItem(getLSName(scenarioName, id, 'packages')) || '{}');
}

export const getSchemaFromLocalStorage = (scenarioName: string, id: string) => {
  if (!scenarioName) {
    console.error('scenarioName is required!');
    return;
  }
  return JSON.parse(window.localStorage.getItem(getLSName(scenarioName, id, 'projectSchema')) || '{}');
}

export const getProjectSchema = async (scenarioName: string = 'unknown', id: string) : Promise<IPublicTypeProjectSchema> => {
  const pageSchema = await getPageSchema(scenarioName, id);
  return generateProjectSchema(pageSchema, DefaultI18nSchema);
};

export const getPageSchema = async (scenarioName: string = 'unknown', id: string) => {
  const pageSchema = getProjectSchemaFromLocalStorage(scenarioName, id)?.componentsTree?.[0];
  if (pageSchema) {
    return pageSchema;
  }

  return DefaultPageSchema;
};

export const getPreviewLocale = (scenarioName: string) => {
  const key = getLSName(scenarioName, undefined, 'previewLocale');
  return window.localStorage.getItem(key) || 'zh-CN';
}

export const setPreviewLocale = (scenarioName: string, locale: string) => {
  const key = getLSName(scenarioName, undefined, 'previewLocale');
  window.localStorage.setItem(key, locale || 'zh-CN');
  window.location.reload();
}

// ------------------------------workspace（项目级）维护---------------------------------------------------------

export const saveWorkspaceSchema = (ctx: IPublicModelPluginContext) => {
  const { config, workspace } = ctx;
  const scenarioName = config.get('scenarioName');
  const { resourceList } = workspace;
  const workspaceSchema: any = {};
  // 保存各页面schema
  resourceList.forEach(r => {
    const { id } = r;
    const schema = getSchemaFromLocalStorage(scenarioName, id);
    console.log('schema', id, schema)
    schema.componentsTree[0].id = schema.componentsTree[0].fileName = id;
    // _merge(workspaceSchema, schema);
    
    if (_isEmpty(workspaceSchema)) {
      Object.assign(workspaceSchema, schema);
    } else {
      workspaceSchema.componentsMap = workspaceSchema.componentsMap.concat(schema.componentsMap);
      workspaceSchema.componentsTree = workspaceSchema.componentsTree.concat(schema.componentsTree);
    }
  });
  // 赋予全局变量
  Object.assign(workspaceSchema, { constants });

  window.localStorage.setItem(
    getLSName(scenarioName, undefined, 'projectSchema'),
    JSON.stringify(workspaceSchema),
  );
  ctx.project.importSchema(workspaceSchema);
  Message.success('成功保存到本地');
};

export const getWorkspaceSchema = (scenarioName: string = 'unknown') : Promise<IPublicTypeProjectSchema> => {
  return getProjectSchemaFromLocalStorage(scenarioName);
};